"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
//抽象类
// 概述：抽象类是⼀种⽆法被实例化的类，专⻔⽤来定义类的结构和⾏为，类中可以写抽象
// ⽅法，也可以写具体实现。抽象类主要⽤来为其派⽣类提供⼀个基础结构，要求其派⽣类
// 必须实现其中的抽象⽅法。
//
// 简记：抽象类不能实例化，其意义是可以被继承，抽象类⾥可以有普通⽅法、也可以有抽
// 象⽅法。
//
//通过以下场景，理解抽象类：
// 我们定义⼀个抽象类 Package ，表示所有包裹的基本结构，任何包裹都有重量属性 weight
// ，包裹都需要计算运费。但不同类型的包裹（如：标准速度、特快专递）都有不同的运费计算
// ⽅式，因此⽤于计算运费的calculate ⽅法是⼀个抽象⽅法，必须由具体的⼦类来实现。
var Package = /** @class */ (function () {
    //构造方法
    function Package(weight) {
        this.weight = weight;
    }
    //具体方法
    Package.prototype.printPackage = function () {
        console.log("\u5305\u88F9\u91CD\u91CF\u4E3A\uFF1A".concat(this.weight, "kg,\u8FD0\u8D39\u4E3A\uFF1A").concat(this.calculate()));
    };
    return Package;
}());
//抽象类不能实例化
// const pa1 = new Package(123)
//StandardPackage 类继承了 Package ，实现了 calculate ⽅法：
var StandardPackage = /** @class */ (function (_super) {
    __extends(StandardPackage, _super);
    //构造方法
    function StandardPackage(weight, unitPrice) {
        var _this = _super.call(this, weight) || this;
        _this.unitPrice = unitPrice;
        return _this;
    }
    // 实现抽象⽅法：计算运费
    StandardPackage.prototype.calculate = function () {
        return this.weight * this.unitPrice;
    };
    return StandardPackage;
}(Package));
var stand1 = new StandardPackage(10, 5);
// console.log(stand1.calculate())
stand1.printPackage();
//ExpressPackage 类继承了 Package ，实现了 calculate ⽅法：
//ExpressPackage 类（特快包裹） 
var ExpressPackage = /** @class */ (function (_super) {
    __extends(ExpressPackage, _super);
    //构造方法
    function ExpressPackage(weight, unitPrice, additional) {
        var _this = _super.call(this, weight) || this;
        _this.weight = weight;
        _this.unitPrice = unitPrice;
        _this.additional = additional;
        return _this;
    }
    //抽象方法实现
    ExpressPackage.prototype.calculate = function () {
        if (this.weight > 10) {
            return 10 * this.unitPrice + (this.weight - 10) * this.additional;
        }
        else {
            return 10 * this.unitPrice;
        }
    };
    return ExpressPackage;
}(Package));
var expre1 = new ExpressPackage(15, 10, 12);
expre1.printPackage();
//总结：何时使⽤抽象类？
// 定义通用接口:为⼀组相关的类定义通⽤的⾏为（⽅法或属性）时。
// 提供基础实现：在抽象类中提供某些⽅法或为其提供基础实现，这样派⽣类就可以继承这些实现。
// 确保关键实现：强制派⽣类实现⼀些关键⾏为。
// 共享代码和逻辑：当多个类需要共享部分代码时，抽象类可以避免代码重复。
